﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once

#include "IIfcObject.h"
#include "OwnerPtr.h"

namespace gcmp
{
    class IIfcEntity;
    class ElementId;

    /// \brief IFC逻辑值，用于创建ValueObject
    enum class IfcLogical : int32_t
    {
        False = 0,
        True = 1,
        Unknown = 2,
        Unset = 3
    };

    /// \brief IFC布尔值，用于创建ValueObject
    enum class IfcBoolean : int32_t
    {
        False = 0,
        True = 1,
        Unset = 2
    };

    /// \brief IFC对象值类型
    /// \note 目前接口支持的类型如下，后续如发现应支持但还未支持的类型，继续添加
    enum class IfcValueType : int32_t
    {
        Unknown     = 0,
        Int         = 1,
        Double      = 2,
        Boolean     = 3,
        String      = 4,
        Logical     = 5,
        IntArray    = 6,
        DoubleArray = 7 
    };

    /// \brief IFC值对象，包括字符型，枚举型，整数型，浮点型，Select型对象
    class GCMP_IFC_INTERFACE_EXPORT IIfcValueObject : public IIfcObject
    {
        DEFINE_CAST_DERIVED(gcmp::IIfcValueObject, gcmp::IIfcObject);
    public:
        /// \brief 创建IFC值对象。
        /// 
        /// 空指针代表默认对象，所以输入参数为"$"或"*"时，返回为空指针
        /// \param upperClassName 要创建的IFC对象的类名，必须全部大写
        /// \param arg 本对象要设置的属性值
        /// \param isSelectType 该对象作为一个selectType类型时传入true，默认为false
        /// \return 返回IFC值对象指针
        ///注意：值对象一般是作为IIfcEntity或IIfcAggregate对象的一个属性存在，字符型，枚举型，整数型，浮点型的值对象都采用该接口创建出来；
        ///创建枚举值时，枚举值对应的字符串前后要加一个点, 参考示例：IIfcValueObject::Create(std::wstring(L"IFCWALLTYPEENUM"), L".MOVABLE.");
        ///创建普通字符串时，对应的字符串前后要加一个单引号, 参考示例：IIfcValueObject::Create(std::wstring(L"IFCIDENTIFIER"), L"'MyIfcIdentifier'");
        ///创建整形和浮点型时，正常传入字符串即可，参考示例：IIfcValueObject::Create(std::wstring(L"IFCPOSITIVELENGTHMEASURE"), L"200.");
        ///在导出参数时，isSelectType需要设置为true
        GCMP_DEPRECATED_API(2023 / 11 / 1) static OwnerPtr<IIfcValueObject> Create(const std::wstring& upperClassName, const std::wstring& arg, bool isSelectType = false);

        /// \brief 创建IFC值对象。
        /// \param upperClassName 要创建的IFC对象的类名，必须全部大写
        /// \param pIfcEntity 本对象要设置的属性值，是一个IFC实体对象指针
        /// \return 返回IFC值对象指针
        ///注意：该方法一般是用于创建Select型对象，其他类型的对象不能使用该接口创建
        GCMP_DEPRECATED_API(2023 / 11 / 1) static OwnerPtr<IIfcValueObject> Create(const std::wstring& upperClassName, const IIfcEntity* pIfcEntity);

        /// \brief 创建IFC值对象。
        /// \param arg 本对象要设置的属性值
        /// \return 返回IFC值对象指针
        ///注意：该方法用于创建不需要传入IFC名字的普通值对象，例如普通int，double类型
        GCMP_DEPRECATED_API(2023 / 11 / 1) static OwnerPtr<IIfcValueObject> Create(const std::wstring& arg);

        /// \brief 创建IfcGloballyUniqueId对象。
        /// \return 返回一个IfcGloballyUniqueId对象指针
        ///基本上每个IfcEntity对象都具有一个IfcGloballyUniqueId对象作为其属性
        static OwnerPtr<IIfcValueObject> CreateIfcGlobalUniqueId();

        /// \brief 根据ElementId创建uniqueId值固定的IfcGloballyUniqueId对象。
        /// \param id ElementId值
        /// \return 返回一个IfcGloballyUniqueId对象指针
        ///一个ElementId值对应的IfcGlobalUniqueId对象的uniqueId是固定的
        static OwnerPtr<IIfcValueObject> CreateFixedGlobalUniqueIdByElementId(const ElementId& id);

        /// \brief 根据int值创建IfcValueObject
        /// \param value int型输入值
        /// \return IIfcValueObject指针
        static OwnerPtr<IIfcValueObject> Create(int value);

        /// \brief 根据int值和对象类名创建IfcValueObject
        /// \param value int型输入值
        /// \param className 对象类名
        /// \param isNumber 是否是Number类型
        /// \return IIfcValueObject指针
        static OwnerPtr<IIfcValueObject> Create(int value, const std::string& className, bool isNumber = false);

        /// \brief 根据double值创建IfcValueObject
        /// \param value double型输入值
        /// \return IIfcValueObject指针
        static OwnerPtr<IIfcValueObject> Create(double value);

        /// \brief 根据double值和对象类名创建IfcValueObject
        /// \param value double型输入值
        /// \param className 对象类名
        /// \param isNumber 是否是Number类型
        /// \return IIfcValueObject指针
        static OwnerPtr<IIfcValueObject> Create(double value, const std::string& className, bool isNumber = false);

        /// \brief 根据IfcBoolean值创建IfcValueObject
        /// \param value IfcBoolean型输入值
        /// \return IIfcValueObject指针
        static OwnerPtr<IIfcValueObject> Create(IfcBoolean value);

        /// \brief 根据IfcBoolean值和对象类名创建IfcValueObject
        /// \param value IfcBoolean型输入值
        /// \param className 对象类名
        /// \return IIfcValueObject指针
        static OwnerPtr<IIfcValueObject> Create(IfcBoolean value, const std::string& className);

        /// \brief 根据IfcLogical值创建IfcValueObject
        /// \param logicType IfcLogical型输入值
        /// \return IIfcValueObject指针
        static OwnerPtr<IIfcValueObject> Create(IfcLogical logicType);

        /// \brief 根据IfcLogical值和对象类名创建IfcValueObject
        /// \param logicType IfcLogical型输入值
        /// \param className 对象类名
        /// \return IIfcValueObject指针
        static OwnerPtr<IIfcValueObject> Create(IfcLogical logicType, const std::string& className);

        /// \brief 根据std::wstring值和对象类名创建IfcValueObject
        /// \param value std::wstring型输入值
        /// \param className 对象类名
        /// \return IIfcValueObject指针
        static OwnerPtr<IIfcValueObject> Create(const std::wstring& value, const std::string& className);

        /// \brief 根据int数组值创建IfcValueObject
        /// \param value int 型数组输入值
        /// \return IIfcValueObject指针
        static OwnerPtr<IIfcValueObject> Create(const std::vector<int>& value);

        /// \brief 根据int数组值和对象类名创建IfcValueObject
        /// \param value int 型数组输入值
        /// \param className 对象类名
        /// \return IIfcValueObject指针
        static OwnerPtr<IIfcValueObject> Create(const std::vector<int>& value, const std::string& className);

        /// \brief 根据double数组值创建IfcValueObject
        /// \param value double 型数组输入值
        /// \return IIfcValueObject指针
        static OwnerPtr<IIfcValueObject> Create(const std::vector<double>& value);

        /// \brief 根据double数组值和对象类名创建IfcValueObject
        /// \param value double 型数组输入值
        /// \param className 对象类名
        /// \return IIfcValueObject指针
        static OwnerPtr<IIfcValueObject> Create(const std::vector<double>& value, const std::string& className);

        /// \brief 以整型获取IFC对象的值
        /// \return 返回IFC对象的值
        virtual int GetValueAsInt() const = 0;

        /// \brief 以浮点型获取IFC对象的值
        /// \return 返回IFC对象的值
        virtual double GetValueAsDouble() const = 0;

        /// \brief 以IfcBoolean类型获取IFC对象的值
        /// \return 返回IFC对象的值
        virtual IfcBoolean GetValueAsBoolean() const = 0;

        /// \brief 以wstring类型获取IFC对象的值
        /// \return 返回IFC对象的值
        virtual std::wstring GetValueAsString() const = 0;

        /// \brief 以IfcLogical类型获取IFC对象的值
        /// \return 返回IFC对象的值
        virtual IfcLogical GetValueAsLogical() const = 0;

        /// \brief 以double数组类型获取IFC对象的值
        /// \return double 数组
        virtual std::vector<double> GetValueAsDoubleArray() const = 0;

        /// \brief 以int数组类型获取IFC对象的值
        /// \return int 数组
        virtual std::vector<int> GetValueAsIntArray() const = 0;

        /// \brief 对IFC值对象克隆。
        /// \return 返回克隆后的值对象指针
        virtual OwnerPtr<IIfcValueObject> Clone() const = 0;

        /// \brief 获取IFC对象是否为selectType类型
        /// \return 返回IFC对象是否为selectType类型
        GCMP_DEPRECATED_API(2023 / 11 / 1) virtual bool IsSelectType() const = 0;

        /// \brief 获取IFC对象的值
        /// \return 返回IFC对象的值,该值是创建对象时的传入值，不管IFC对象内部存放的是整形，浮点，枚举值，字符串，都是以std::wstring的形式返回
        virtual std::wstring GetValue() const = 0;

        /// \brief 析构函数
        virtual ~IIfcValueObject() {}

        /// \brief 获取该IFC对象的类名。
        /// \return 返回该IFC对象的类名引用
        ///注意：返回的类名是IFC三方库中导出的类名，目前都是大写字符
        virtual const std::wstring& GetIfcClassName() const = 0;

        /// \brief 获取该IFC对象的值类型
        /// \return 获取当前IFC对象的值类型
        virtual IfcValueType GetValueType() const = 0;
    };
}
